package com.plian.system.service.pf.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.common.status.CustomCode;
import com.plian.system.constant.baseinfo.ValueSetConstant;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.dao.sys.orgzation.OrgzationDao;
import com.plian.system.dao.sys.user.UserDao;
import com.plian.system.dto.pf.BaseGrantSalaryDTO;
import com.plian.system.entity.pf.BaseChildGrantSalary;
import com.plian.system.entity.pf.BaseGrantSalary;
import com.plian.system.entity.pf.ChildGrantSalary;
import com.plian.system.entity.pf.GrantSalary;
import com.plian.system.entity.pm.propertyinformation.PropertyTime;
import com.plian.system.entity.sys.IgnoreMessageInfo;
import com.plian.system.entity.sys.Message;
import com.plian.system.mapper.pf.BaseGrantSalaryMapper;
import com.plian.system.mapper.pf.GrantSalaryMapper;
import com.plian.system.mapper.pf.SalarySummaryRelationMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.ListResult;
import com.plian.system.model.ObjResult;
import com.plian.system.model.R;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.mybatis.search.SearchEntity;
import com.plian.system.mybatis.search.SearchParamEntiy;
import com.plian.system.mybatis.support.Condition;
import com.plian.system.mybatis.support.Query;
import com.plian.system.properties.GzwProperties;
import com.plian.system.service.bt.baseinfo.BaseInfoService;
import com.plian.system.service.pf.*;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.message.IIgnoreMessageInfoService;
import com.plian.system.service.sys.orgzation.OrgzationService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.service.wfTwo.WorkflowTwoService;
import com.plian.system.vo.pf.*;
import com.plian.system.vo.report.HeaderVO;
import com.plian.system.vo.report.ReportReturnVO;
import com.plian.system.vo.report.ReportVO;
import com.plian.system.vo.sys.UserRoleInfoVO;
import com.plian.system.wrapper.pf.BaseGrantSalaryWrapper;
import com.plian.system.wrapper.pf.GrantSalaryWrapper;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * 职工工资发放主表_集团 服务实现类
 *
 * @author
 * @since 2019-09-27
 */
@Service
@AllArgsConstructor
public class BaseGrantSalaryServiceImpl extends BaseServiceImpl<BaseGrantSalaryMapper, BaseGrantSalary> implements IBaseGrantSalaryService, BaseFlowService {

	private FormWorkflowService formWorkflowService;

	private IFormCodeService formCodeService;

	private IGrantSalaryService grantSalaryService;

	private BaseInfoService baseInfoService;

	private OrgzationService orgzationService;

	private IBaseChildGrantSalaryService baseChildGrantSalaryService;

	private IChildGrantSalaryService childGrantSalaryService;

	private GrantSalaryMapper grantSalaryMapper;

	private ISalarySummaryRelationService salarySummaryRelationService;

	private SalarySummaryRelationMapper salarySummaryRelationMapper;

	private Environment environment;

	private OrgzationDao orgzationDao;

	private UserDao userDao;

	private BaseGrantSalaryWrapper baseGrantSalaryWrapper;

	private GrantSalaryWrapper grantSalaryWrapper;

	private GzwProperties gzwProperties;

	private IIgnoreMessageInfoService ignoreMessageInfoService;

	private WorkflowTwoService workflowTwoService;

	private static final Logger log = LoggerFactory.getLogger(BaseGrantSalaryServiceImpl.class);

	@Override
	public boolean saveOrUpdate(BaseGrantSalary baseGrantSalary) {

		if (!Optional.ofNullable(baseGrantSalary.getStatus()).isPresent()) {
			baseGrantSalary.setStatus(FormStatusConstant.UNREVIEWED);
		}
		if (!Optional.ofNullable(baseGrantSalary.getId()).isPresent()) {
			baseGrantSalary.setCode(formCodeService.getCode(FormTypeConstant.PF_BASE_GRANT_SALARY));
			baseGrantSalary.setFormType(String.valueOf(FormTypeConstant.PF_BASE_GRANT_SALARY));
		}

		return super.saveOrUpdate(baseGrantSalary);
	}

	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public boolean deleteLogic(List<Long> ids) {
		for (Long id : ids) {
			BaseGrantSalary baseGrantSalary = getById(id);
			if (baseGrantSalary == null) {
				return false;
			} else if (baseGrantSalary.getStatus() != null &&
					(baseGrantSalary.getStatus() != FormStatusConstant.STASH && baseGrantSalary.getStatus() != FormStatusConstant.UNREVIEWED)) {
				return false;
			}
			formWorkflowService.deleteProcessInstance(String.valueOf(id));
		}

		boolean result = super.deleteLogic(ids);
		if (result){
			grantSalaryService.deleteByParentId(ids);
		}

		return result;
	}

	@Override
	public HashMap<String,Object> commit(String id) {
		handleStatus(Long.valueOf(id), FormStatusConstant.FLOW);

		//将需要提交的流程变量返回，用于工作流侧
		return new HashMap<String,Object>();
	}

	@Override
	public Boolean finish(String id) {
		return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH);
	}

	@Override
	public Boolean reject(String id, int formState, String comment) {
		return handleStatus(Long.valueOf(id), formState);
	}

	@Override
	public String checkMonth(BaseGrantSalary baseGrantSalary) {
		LambdaQueryWrapper<BaseGrantSalary> queryWrapper = new LambdaQueryWrapper<>();
		if (!Optional.ofNullable(baseGrantSalary.getFillingMonth()).isPresent()) {
			return "填报时间为空";
		}
		if (!Optional.ofNullable(baseGrantSalary.getFillingUnitId()).isPresent()){
			return "填报单位为空";
		}
		queryWrapper.eq(BaseGrantSalary::getFillingUnitId,baseGrantSalary.getFillingUnitId());
		queryWrapper.eq(BaseGrantSalary::getFillingMonth, baseGrantSalary.getFillingMonth());
		queryWrapper.eq(BaseGrantSalary::getType, baseGrantSalary.getType());
		BaseGrantSalary one = getOne(queryWrapper);
		if (!Optional.ofNullable(one).isPresent()){
			return null;
		}
		if (one.getId().equals(baseGrantSalary.getId())){
			return null;
		}
		return "该月份已填报";
	}


	/**
	 * 统一处理状态机事件方法
	 *
	 * @param id          主键
	 * @param updateStatus  更新状态
	 * @return boolean
	 */
	private Boolean handleStatus(Long id, int updateStatus) {
		try {
			BaseGrantSalary baseGrantSalary = getById(id);
			/**
			 * 设置审批人和审批时间
			 */
			if (updateStatus == FormStatusConstant.FINISH){
				baseGrantSalary.setApprovedUser(TokenUtil.getTokenUserId());
				Date now = DateUtil.now();
				baseGrantSalary.setApprovedTime(now);
			}
			baseGrantSalary.setStatus(updateStatus);
			updateById(baseGrantSalary);
			return true;
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
			return false;
		}
	}


	@Override
	public List<PageData> findByIds(List<String> formIds) {
		QueryWrapper<BaseGrantSalary> queryWrapper = new QueryWrapper<>();
		queryWrapper.in("id", Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
		List<BaseGrantSalary> baseGrantSalaries = list(queryWrapper);
		List<BaseGrantSalaryVO> baseGrantSalaryVOS= baseGrantSalaryWrapper.entityToVO(baseGrantSalaries);
		List<PageData> pageDataList = new ArrayList<>();
		try{
			if (CollectionUtil.isNotEmpty(baseGrantSalaryVOS)){
				for (BaseGrantSalaryVO vo : baseGrantSalaryVOS){
					PageData pd = new PageData();
					pd.put("id", vo.getId());
					pd.put("UNITNAME", vo.getFillingUnitName());
					pd.put("APPLICANTNAME", vo.getCreateUserName());
					pd.put("applicantId", vo.getCreateUser());
					pd.put("applyOrganizationId", vo.getFillingUnitId());
					pd.put("formType", FormTypeConstant.PF_BASE_GRANT_SALARY);
					pd.put("orgName", vo.getFillingUnitName());
					pd.put("salaryType", vo.getType());
					pageDataList.add(pd);
				}
			}

			return pageDataList;
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
		return pageDataList;
	}

	@Override
	public List<Integer> getFormType() {
		return Collections.singletonList(FormTypeConstant.PF_BASE_GRANT_SALARY);
	}

	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public boolean submit(BaseGrantSalary baseGrantSalary) {
		boolean result = saveOrUpdate(baseGrantSalary);
		if (result){
			List<GrantSalary> grantSalaries = baseGrantSalary.getGrantSalaries();
			if (CollectionUtil.isNotEmpty(grantSalaries)){
				for (GrantSalary grantSalary : grantSalaries){
					if (grantSalary.getId() != null &&
							Optional.ofNullable(grantSalary.getIsDeleted()).isPresent() && grantSalary.getIsDeleted().intValue() == 1) {
						grantSalaryService.removeById(grantSalary.getId());
					}else {
						grantSalary.setBaseGrantSalaryId(baseGrantSalary.getId());
						grantSalary.setOnJobTotalNumber(BigDecimalUtil.add(grantSalary.getOnJobNumber(), grantSalary.getOnJobLastTotalNumber()));
						grantSalaryService.saveOrUpdate(grantSalary);
					}
				}
			}

			List<String> childIds = baseGrantSalary.getChildIds();
			if (CollectionUtil.isNotEmpty(childIds)){
				salarySummaryRelationService.submit(baseGrantSalary.getId(), childIds.stream().map(childId -> Long.valueOf(childId)).collect(Collectors.toList()));
			}
			if(baseGrantSalary.getStatus() == 3){
				// 反审核
				goBackToStash(String.valueOf(baseGrantSalary.getId()));
				workflowTwoService.goBackToStash(String.valueOf(baseGrantSalary.getId()), FormTypeConstant.HR_STAFFFILES_FORM);
			}
		}
		return result;
	}

	@Override
	public R<BaseGrantSalaryVO> getDetailObj(BaseGrantSalaryVO baseGrantSalaryVO) {
		if(!Optional.ofNullable(baseGrantSalaryVO).isPresent()){
			return new R(CommonCode.FAIL);
		}
		baseGrantSalaryVO.setGrantSalaryVOS(grantSalaryWrapper.entityToVO(grantSalaryService.list(new LambdaQueryWrapper<GrantSalary>()
				.eq(GrantSalary::getBaseGrantSalaryId, baseGrantSalaryVO.getId()))));
		R<BaseGrantSalaryVO> r=getLastMonthObj(baseGrantSalaryVO);
		if(r.getPageData()!=null&&r.getPageData().getGrantSalaryVOS()!=null){
			baseGrantSalaryVO.setLastGrantSalaryVOS(getLastMonthObj(baseGrantSalaryVO).getPageData().getGrantSalaryVOS());
		}
		R<BaseGrantSalaryVO> objResult = new R<>(CommonCode.SUCCESS);
		objResult.setPageData(baseGrantSalaryVO);
		return objResult;
	}

	@Override
	public void goBackToStash(String formId) {
		handleStatus(Long.valueOf(formId), UNREVIEWED);
	}


	@Override
	public R<BaseGrantSalaryVO> getLastMonthObj(BaseGrantSalary baseGrantSalary) {
		String fillingMonth = baseGrantSalary.getFillingMonth();

		if (StringUtil.isBlank(fillingMonth)){
			return new R(CustomCode.builder().message("填报年月为空").code(1999).success(false).build());
		}

		Calendar c = Calendar.getInstance();
		Date lastDate = DateUtil.parse(fillingMonth, DateUtil.PATTERN_MONTH);
		c.setTime(lastDate);
		c.add(Calendar.MONTH, -1);
		String lastMonth = DateUtil.format(c.getTime(), DateUtil.PATTERN_MONTH);
		BaseGrantSalary last = null;
		Integer type = baseGrantSalary.getType();
		// 判断2个日期是否为同一年
		if (DateUtil.isTheSameYear(lastDate, c.getTime())){
			last = getOne(new LambdaQueryWrapper<BaseGrantSalary>()
					.eq(BaseGrantSalary::getFillingUnitId, TokenUtil.getTokenOrgId())
					.eq(BaseGrantSalary::getFillingMonth, lastMonth)
					.eq(BaseGrantSalary::getType, type));
		}

		//上月数据
		List<GrantSalaryVO> grantSalaryVOS = new ArrayList<>();
		if (Optional.ofNullable(last).isPresent()){
			grantSalaryVOS = grantSalaryWrapper.entityToVO(grantSalaryService.list(new LambdaQueryWrapper<GrantSalary>()
					.eq(GrantSalary::getBaseGrantSalaryId, last.getId())));
		}

		// 获取本年已填报数据
		String fillingYear = fillingMonth.split(StringPool.DASH)[0];
		List<BaseGrantSalary> baseList = list(new LambdaQueryWrapper<BaseGrantSalary>()
				.eq(BaseGrantSalary::getFillingUnitId, TokenUtil.getTokenOrgId())
				.eq(BaseGrantSalary::getType, type)
				.like(BaseGrantSalary::getFillingMonth, fillingYear));
		List<GrantSalary> grantSalaries = new ArrayList<>();
		if (CollectionUtil.isNotEmpty(baseList)) {
			grantSalaries = grantSalaryService.list(new LambdaQueryWrapper<GrantSalary>()
					.eq(GrantSalary::getBaseGrantSalaryId, baseList.get(0).getId()));
		}

		String lastFillingYear = String.valueOf(Integer.valueOf(fillingMonth.split("-")[0]) - 1);


		List<String> fillingUnitIds = new ArrayList<>();
		fillingUnitIds.add(TokenUtil.getTokenOrgId());

		R<BaseGrantSalaryVO> objResult = new R<>(CommonCode.SUCCESS);
		BaseGrantSalaryVO baseGrantSalaryVO = new BaseGrantSalaryVO();
		baseGrantSalaryVO.setGrantSalaryVOS(init(grantSalaryVOS, lastFillingYear, fillingUnitIds, grantSalaries,
				type, orgzationService.isUnit(TokenUtil.getTokenOrgId())));
		objResult.setPageData(baseGrantSalaryVO);
		return objResult;
	}

	private List<SalaryMonthStatisticsVO> getList(String year, List<String> fillingUnitIds, Integer type){
		List<SalaryMonthStatisticsVO> results = new ArrayList<>();
		for (String fillingUnitId : fillingUnitIds){
			List<BaseGrantSalary> baseList = list(new LambdaQueryWrapper<BaseGrantSalary>()
					.eq(BaseGrantSalary::getStatus, FormStatusConstant.FINISH)
					.eq(BaseGrantSalary::getFillingUnitId, fillingUnitId)
					.eq(BaseGrantSalary::getType, type)
					.like(BaseGrantSalary::getFillingMonth, year));
			String orgName = orgzationService.getNameById(fillingUnitId);
			List<SalaryMonthStatisticsVO> data = initSummary(type, orgName);
			results.addAll(data);
			if (CollectionUtil.isNotEmpty(baseList)){
				Map<Long, List<BaseGrantSalary>> baseMap = baseList.stream().collect(Collectors.groupingBy(BaseGrantSalary::getId));
				List<GrantSalary> grantSalaries = grantSalaryService.list(new LambdaQueryWrapper<GrantSalary>()
						.in(GrantSalary::getBaseGrantSalaryId, baseList.stream().map(BaseGrantSalary::getId).collect(Collectors.toList())));
				// 按集团工资统计类型分类
				Map<String, List<GrantSalary>> map = grantSalaries.stream().collect(Collectors.groupingBy(GrantSalary::getCountCategoryId));

				//集团赋值
				for (SalaryMonthStatisticsVO result : data){
					if (map.containsKey(result.getCountCategoryId())){
						BigDecimal onJobNumber = new BigDecimal(0);
						BigDecimal total = new BigDecimal(0);
						BigDecimal totalProvision = new BigDecimal(0);
						for (GrantSalary grantSalary : map.get(result.getCountCategoryId())){
							setValue(grantSalary, result, baseMap.get(grantSalary.getBaseGrantSalaryId()).get(0).getFillingMonth());
							if (Optional.ofNullable(grantSalary.getActualGrantAmount()).isPresent()){
								total = total.add(grantSalary.getActualGrantAmount());
							}
							if (Optional.ofNullable(grantSalary.getActualProvisionThisMonth()).isPresent()){
								totalProvision = totalProvision.add(grantSalary.getActualProvisionThisMonth());
							}
							onJobNumber = BigDecimalUtil.add(onJobNumber, grantSalary.getOnJobNumber());
						}

						int size = map.get(result.getCountCategoryId()).size();
						GrantSalary grantSalary = map.get(result.getCountCategoryId()).get(size - 1);
						result.setMonthAverage(BigDecimalUtil.divide(onJobNumber, new BigDecimal(size), 4, BigDecimal.ROUND_HALF_UP));
						result.setYearAverage(result.getMonthAverage());
						result.setTotalActualGrantAmount(total);
						result.setTotalActualProvision(totalProvision);
						result.setBudget(grantSalary.getBudget());
						result.setGrantProgress(BigDecimalUtil.divide(total, grantSalary.getBudget(), 4, BigDecimal.ROUND_HALF_UP, 100));
						result.setAverageSalary(BigDecimalUtil.divide(total, result.getMonthAverage(), 4, BigDecimal.ROUND_HALF_UP));
						result.setLastAverageSalary(grantSalary.getAverageSalary());
						result.setActualPeopleNumber(grantSalary.getActualPeopleNumber());
						if (Optional.ofNullable(result.getAverageSalary()).isPresent() && Optional.ofNullable(result.getLastAverageSalary()).isPresent()){
							result.setWageIncreases(BigDecimalUtil.divide(BigDecimalUtil.subtract(result.getAverageSalary(), result.getLastAverageSalary()),
									result.getLastAverageSalary(), 4, BigDecimal.ROUND_HALF_UP, 100));
						}

					}
				}
			}
		}

		return results;
	}


	private void endSum(SalaryMonthStatisticsVO end, SalaryMonthStatisticsVO result){
		end.setMonthAverage(BigDecimalUtil.add(end.getMonthAverage() , result.getMonthAverage()));
		// 12个月在岗人数
		end.setJanuaryOnJobNumber(BigDecimalUtil.add(end.getJanuaryOnJobNumber() , result.getJanuaryOnJobNumber()));
		end.setFebruaryOnJobNumber(BigDecimalUtil.add(end.getFebruaryOnJobNumber() , result.getFebruaryOnJobNumber()));
		end.setMarchOnJobNumber(BigDecimalUtil.add(end.getMarchOnJobNumber() , result.getMarchOnJobNumber()));
		end.setAprilOnJobNumber(BigDecimalUtil.add(end.getAprilOnJobNumber() , result.getAprilOnJobNumber()));
		end.setMayOnJobNumber(BigDecimalUtil.add(end.getMayOnJobNumber() , result.getMayOnJobNumber()));
		end.setJuneOnJobNumber(BigDecimalUtil.add(end.getJuneOnJobNumber() , result.getJuneOnJobNumber()));
		end.setJulyOnJobNumber(BigDecimalUtil.add(end.getJuneOnJobNumber() , result.getJulyOnJobNumber()));
		end.setAugustOnJobNumber(BigDecimalUtil.add(end.getAugustOnJobNumber() , result.getAugustOnJobNumber()));
		end.setSeptemberOnJobNumber(BigDecimalUtil.add(end.getSeptemberOnJobNumber() , result.getSeptemberOnJobNumber()));
		end.setOctoberOnJobNumber(BigDecimalUtil.add(end.getOctoberOnJobNumber() , result.getOctoberOnJobNumber()));
		end.setNovemberOnJobNumber(BigDecimalUtil.add(end.getNovemberOnJobNumber() , result.getNovemberOnJobNumber()));
		end.setDecemberOnJobNumber(BigDecimalUtil.add(end.getDecemberOnJobNumber() , result.getDecemberOnJobNumber()));
		end.setYearAverage(BigDecimalUtil.add(end.getYearAverage(), result.getYearAverage()));


		end.setTotalActualGrantAmount(BigDecimalUtil.add(end.getTotalActualGrantAmount() , (result.getTotalActualGrantAmount())));
		end.setTotalActualProvision(BigDecimalUtil.add(end.getTotalActualProvision() , (result.getTotalActualProvision())));
		// 12个月实际发放
		end.setJanuaryActualGrantAmount(BigDecimalUtil.add(end.getJanuaryActualGrantAmount() , (result.getJanuaryActualGrantAmount())));
		end.setFebruaryActualGrantAmount(BigDecimalUtil.add(end.getFebruaryActualGrantAmount() , (result.getFebruaryActualGrantAmount())));
		end.setMarchActualGrantAmount(BigDecimalUtil.add(end.getMarchActualGrantAmount() , (result.getMarchActualGrantAmount())));
		end.setAprilActualGrantAmount(BigDecimalUtil.add(end.getAprilActualGrantAmount() , (result.getAprilActualGrantAmount())));
		end.setMayActualGrantAmount(BigDecimalUtil.add(end.getMayActualGrantAmount() , (result.getMayActualGrantAmount())));
		end.setJuneActualGrantAmount(BigDecimalUtil.add(end.getJuneActualGrantAmount() , (result.getJuneActualGrantAmount())));
		end.setJulyActualGrantAmount(BigDecimalUtil.add(end.getJuneActualGrantAmount() , (result.getJulyActualGrantAmount())));
		end.setAugustActualGrantAmount(BigDecimalUtil.add(end.getAugustActualGrantAmount() , (result.getAugustActualGrantAmount())));
		end.setSeptemberActualGrantAmount(BigDecimalUtil.add(end.getSeptemberActualGrantAmount() , (result.getSeptemberActualGrantAmount())));
		end.setOctoberActualGrantAmount(BigDecimalUtil.add(end.getOctoberActualGrantAmount() , (result.getOctoberActualGrantAmount())));
		end.setNovemberActualGrantAmount(BigDecimalUtil.add(end.getNovemberActualGrantAmount() , (result.getNovemberActualGrantAmount())));
		end.setDecemberActualGrantAmount(BigDecimalUtil.add(end.getDecemberActualGrantAmount() , (result.getDecemberActualGrantAmount())));

		end.setAverageSalary(BigDecimalUtil.add(end.getAverageSalary() , (result.getAverageSalary())));
		end.setLastAverageSalary(BigDecimalUtil.add(end.getLastAverageSalary() , (result.getLastAverageSalary())));
		end.setActualPeopleNumber(BigDecimalUtil.add(end.getActualPeopleNumber() , result.getActualPeopleNumber()));
	}

	@Override
	public ReportReturnVO yearStatistics(BaseGrantSalaryDTO baseGrantSalaryDTO) {
		List<SalaryMonthStatisticsVO> results = new ArrayList<>();
		List<SalaryMonthStatisticsVO> totalList = getList(baseGrantSalaryDTO.getFillingYear(), baseGrantSalaryDTO.getFillingUnitIds(), 2);
		if (CollectionUtil.isNotEmpty(totalList)){
			results.addAll(totalList);
		}
//		List<SalaryMonthStatisticsVO> cadreList = getList(baseGrantSalaryDTO.getFillingYear(), baseGrantSalaryDTO.getFillingUnitIds(), 1);
//		if (CollectionUtil.isNotEmpty(cadreList)){
//			results.addAll(cadreList);
//		}
//		SalaryMonthStatisticsVO end = SalaryMonthStatisticsVO.builder().countCategoryName("合计").build();
//		for (SalaryMonthStatisticsVO baseVO : results){
//			endSum(end, baseVO);
//		}
//		results.add(0, end);

//		List<SalaryMonthStatisticsVO> allChildResults = baseChildGrantSalaryService
//				.yearStatistics(baseGrantSalaryDTO.getFillingYear(), baseGrantSalaryDTO.getFillingUnitIds());
//		if(CollectionUtil.isNotEmpty(allChildResults)){
//			endSum(end, allChildResults.get(0));
//		}
//		end.setGrantProgress(BigDecimalUtil.divide(end.getTotalActualGrantAmount(), end.getBudget(), 4, BigDecimal.ROUND_HALF_UP, 100));
//		if (Optional.ofNullable(end.getAverageSalary()).isPresent() && Optional.ofNullable(end.getLastAverageSalary()).isPresent()) {
//			end.setWageIncreases(end.getAverageSalary().subtract(end.getLastAverageSalary())
//					.multiply(new BigDecimal(100)).divide(end.getLastAverageSalary(), 4, BigDecimal.ROUND_HALF_UP));
//		}

//		results.addAll(allChildResults);

		ReportReturnVO reportReturnVO = new ReportReturnVO();
		ReportVO reportVO = new ReportVO();

		reportVO
				.addHeader(HeaderVO.builder().key("countCategoryName").title("项目名称").build())
				.addHeader(HeaderVO.builder().key("monthAverage").title("职工月度平均人数（人）").build())
                .addHeader(HeaderVO.builder().key("januaryOnJobNumber").title("1月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("februaryOnJobNumber").title("2月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("marchOnJobNumber").title("3月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("aprilOnJobNumber").title("4月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("mayOnJobNumber").title("5月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("juneOnJobNumber").title("6月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("julyOnJobNumber").title("7月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("augustOnJobNumber").title("8月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("septemberOnJobNumber").title("9月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("octoberOnJobNumber").title("10月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("novemberOnJobNumber").title("11月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("decemberOnJobNumber").title("12月份在岗人数").build())
                .addHeader(HeaderVO.builder().key("yearAverage").title("职工年度平均人数（人）").build())
                .addHeader(HeaderVO.builder().key("totalActualGrantAmount").title("实际发放年度合计数（万元）").build())
                .addHeader(HeaderVO.builder().key("januaryActualGrantAmount").title("1月份实际发放").build())
                .addHeader(HeaderVO.builder().key("februaryActualGrantAmount").title("2月份实际发放").build())
                .addHeader(HeaderVO.builder().key("marchActualGrantAmount").title("3月份实际发放").build())
                .addHeader(HeaderVO.builder().key("aprilActualGrantAmount").title("4月份实际发放").build())
                .addHeader(HeaderVO.builder().key("mayActualGrantAmount").title("5月份实际发放").build())
                .addHeader(HeaderVO.builder().key("juneActualGrantAmount").title("6月份实际发放").build())
                .addHeader(HeaderVO.builder().key("julyActualGrantAmount").title("7月份实际发放").build())
                .addHeader(HeaderVO.builder().key("augustActualGrantAmount").title("8月份实际发放").build())
                .addHeader(HeaderVO.builder().key("septemberActualGrantAmount").title("9月份实际发放").build())
                .addHeader(HeaderVO.builder().key("octoberActualGrantAmount").title("10月份实际发放").build())
                .addHeader(HeaderVO.builder().key("novemberActualGrantAmount").title("11月份实际发放").build())
                .addHeader(HeaderVO.builder().key("decemberActualGrantAmount").title("12月份实际发放").build())
                .addHeader(HeaderVO.builder().key("budget").title("年度预算总额").build())
                .addHeader(HeaderVO.builder().key("grantProgress").title("工资发放进度%").build())
                .addHeader(HeaderVO.builder().key("averageSalary").title("年度平均工资").build())
                .addHeader(HeaderVO.builder().key("lastAverageSalary").title("上年度平均工资").build())
                .addHeader(HeaderVO.builder().key("actualPeopleNumber").title("上年度平均实际人数").build())
                .addHeader(HeaderVO.builder().key("wageIncreases").title("平均工资增幅 %").build());
		reportVO.setData(results);
		reportReturnVO.setGrids(reportVO);
		return reportReturnVO;
	}

	@Override
	public ListResult<PageData> treeList(Query query) {
		log.info("====================职工工资发放管理查询开始==================");
		List<SearchEntity> entityList = query.getSearch();
		if (query.getAscs()==null&&query.getDescs()==null){
			query.setDescs("filling_month");
		}
		QueryWrapper<BaseGrantSalary> queryWrapper = SearchParamEntiy.getQueryWrapper(
				Condition.getQueryWrapper(new BaseGrantSalary()), entityList
		);
		queryWrapper.eq("create_company_id", TokenUtil.getTokenOrgId());

		if (orgzationService.isParent(TokenUtil.getTokenOrgId())){
			queryWrapper.eq("type", 2);
		}else {
			queryWrapper.eq("type", 1);
		}

		IPage<BaseGrantSalary> pages = page(Condition.getPage(query), queryWrapper);
		List<BaseGrantSalaryVO> baseWelfareExpendVOS = baseGrantSalaryWrapper.entityToVO(pages.getRecords());
		List<PageData> pageDataList = new ArrayList<>();
		if (CollectionUtil.isNotEmpty(baseWelfareExpendVOS)){
			for (BaseGrantSalaryVO vo : baseWelfareExpendVOS){
				PageData pd = new PageData();
				pd.put("createUser", vo.getCreateUser());
				pd.put("fillingUnitId", vo.getFillingUnitId());
				pd.put("fillingUnitName", vo.getFillingUnitName());
				pd.put("fillingMonth", vo.getFillingMonth());
				pd.put("baseGrantSalaryId", vo.getId().toString());
				if (vo.getType() == 1){
					pd.put("typeName", "单户表");
				}else {
					pd.put("typeName", "集团合并表");
				}
				pd.put("formType", FormTypeConstant.PF_BASE_GRANT_SALARY);
				pd.put("type", vo.getType());
				pd.put("status", vo.getStatus());
				pageDataList.add(pd);
			}
		}
		ListResult<PageData> listResult = new ListResult<>(CommonCode.SUCCESS);
		listResult.setList(pageDataList);
		listResult.setTotal(Long.valueOf(pages.getTotal()).intValue());
		log.info("====================职工工资发放管理结果集：{}==================",pageDataList);
		log.info("====================职工工资发放管理查询结束==================");
		return listResult;

	}

	@Override
	public ObjResult getSummaryObj(BaseGrantSalary baseGrantSalary) {
		String fillingUnitId = baseGrantSalary.getFillingUnitId();
		String fillingMonth = baseGrantSalary.getFillingMonth();
		if (StringUtil.isBlank(fillingUnitId)){
			return new ObjResult(CustomCode.builder().message("填报单位为空").code(1999).success(false).build());
		}
		if (StringUtil.isBlank(fillingMonth)){
			return new ObjResult(CustomCode.builder().message("填报年月为空").code(1999).success(false).build());
		}
		List<GrantSalarySummaryVO> results = new ArrayList<>();
		//本级
		BaseGrantSalary base = getOne(new LambdaQueryWrapper<BaseGrantSalary>().eq(BaseGrantSalary::getFillingUnitId, fillingUnitId)
				.eq(BaseGrantSalary::getFillingMonth, fillingMonth));
		List<GrantSalary> grantSalaries = new ArrayList<>();
		if (Optional.ofNullable(base).isPresent()) {
			grantSalaries = grantSalaryService.list(new LambdaQueryWrapper<GrantSalary>().eq(GrantSalary::getBaseGrantSalaryId, base.getId()));
		}

		String fillingUnitName = "";
		PageData org = orgzationService.getCompanyNameById(fillingUnitId);
		if (Optional.ofNullable(org).isPresent()){
			fillingUnitName = (String)org.get("name");
		}

		List<GrantSalarySummaryVO> grantSalarySummaryVOS = firstSet(fillingUnitId, fillingUnitName, grantSalaries);
		GrantSalarySummaryVO total = GrantSalarySummaryVO.builder().countCategoryName("合计").build();
		if (CollectionUtil.isNotEmpty(grantSalarySummaryVOS)){
			for(GrantSalarySummaryVO salarySummaryVO : grantSalarySummaryVOS) {
				if ("085002".equals(salarySummaryVO.getCountCategoryId())
						|| "085006".equals(salarySummaryVO.getCountCategoryId())) {
					total.setOnJobNumber(BigDecimalUtil.add(total.getOnJobNumber(), salarySummaryVO.getOnJobNumber()));
					total.setCumulativeGrantAmount(BigDecimalUtil.add(total.getCumulativeGrantAmount(), salarySummaryVO.getCumulativeGrantAmount()));
					total.setActualGrantAmount(BigDecimalUtil.add(total.getActualGrantAmount(), salarySummaryVO.getActualGrantAmount()));
					total.setBudget(BigDecimalUtil.add(total.getBudget(), salarySummaryVO.getBudget()));
					total.setLastYearSalary(BigDecimalUtil.add(total.getLastYearSalary(), salarySummaryVO.getLastYearSalary()));
					total.setActualPeopleNumber(BigDecimalUtil.add(total.getActualPeopleNumber(), salarySummaryVO.getActualPeopleNumber()));
					total.setLastCumulativeGrantAmount(BigDecimalUtil.add(total.getLastCumulativeGrantAmount(), salarySummaryVO.getLastCumulativeGrantAmount()));

					total.setCumulativeProvisionThisYear(BigDecimalUtil.add(total.getCumulativeProvisionThisYear(), salarySummaryVO.getCumulativeProvisionThisYear()));
					total.setActualProvisionThisMonth(BigDecimalUtil.add(total.getActualProvisionThisMonth(), salarySummaryVO.getActualProvisionThisMonth()));
					total.setActualProvisionLastYear(BigDecimalUtil.add(total.getActualProvisionLastYear(), salarySummaryVO.getActualProvisionLastYear()));
					total.setActualProvisionToLastMonth(BigDecimalUtil.add(total.getActualProvisionToLastMonth(), salarySummaryVO.getActualProvisionToLastMonth()));
				}
			}
		}
		results.add(total);
		results.addAll(grantSalarySummaryVOS);
		// 子企业
		List<String> childIds = getChildIds(fillingUnitId);
		if (CollectionUtil.isNotEmpty(childIds)){
			List<BaseChildGrantSalary> baseChildGrantSalaries = baseChildGrantSalaryService.list(new LambdaQueryWrapper<BaseChildGrantSalary>()
					.in(BaseChildGrantSalary::getFillingUnitId, childIds).eq(BaseChildGrantSalary::getFillingMonth, fillingMonth));
			Map<String, Long> baseChildMap = new HashMap<>();
			Map<Long, List<ChildGrantSalary>> childGrantSalaryMap = new HashMap<>();
			if (CollectionUtil.isNotEmpty(baseChildGrantSalaries)){
				for (BaseChildGrantSalary baseChildGrantSalary : baseChildGrantSalaries){
					baseChildMap.put(baseChildGrantSalary.getFillingUnitId(), baseChildGrantSalary.getId());
				}
				List<ChildGrantSalary> childGrantSalaries = childGrantSalaryService.list(new LambdaQueryWrapper<ChildGrantSalary>()
						.in(ChildGrantSalary::getBaseChildGrantSalaryId, baseChildGrantSalaries.stream().map(BaseChildGrantSalary::getId).collect(Collectors.toList())));
				childGrantSalaryMap = childGrantSalaries.stream().collect(Collectors.groupingBy(ChildGrantSalary::getBaseChildGrantSalaryId));
			}
			List<GrantSalarySummaryVO> childGrantSalarySummaryVOS = childSet(childIds, baseChildMap, childGrantSalaryMap);
			if (CollectionUtil.isNotEmpty(childGrantSalarySummaryVOS)){
				GrantSalarySummaryVO salarySummaryVO = childGrantSalarySummaryVOS.get(0);
				total.setOnJobNumber(BigDecimalUtil.add(total.getOnJobNumber(), salarySummaryVO.getOnJobNumber()));
				total.setCumulativeGrantAmount(BigDecimalUtil.add(total.getCumulativeGrantAmount(), salarySummaryVO.getCumulativeGrantAmount()));
				total.setActualGrantAmount(BigDecimalUtil.add(total.getActualGrantAmount(), salarySummaryVO.getActualGrantAmount()));
				total.setBudget(BigDecimalUtil.add(total.getBudget(), salarySummaryVO.getBudget()));
				total.setLastYearSalary(BigDecimalUtil.add(total.getLastYearSalary(), salarySummaryVO.getLastYearSalary()));
				total.setActualPeopleNumber(BigDecimalUtil.add(total.getActualPeopleNumber(), salarySummaryVO.getActualPeopleNumber()));
				total.setLastCumulativeGrantAmount(BigDecimalUtil.add(total.getLastCumulativeGrantAmount(), salarySummaryVO.getLastCumulativeGrantAmount()));

				total.setCumulativeProvisionThisYear(BigDecimalUtil.add(total.getCumulativeProvisionThisYear(), salarySummaryVO.getCumulativeProvisionThisYear()));
				total.setActualProvisionThisMonth(BigDecimalUtil.add(total.getActualProvisionThisMonth(), salarySummaryVO.getActualProvisionThisMonth()));
				total.setActualProvisionLastYear(BigDecimalUtil.add(total.getActualProvisionLastYear(), salarySummaryVO.getActualProvisionLastYear()));
				total.setActualProvisionToLastMonth(BigDecimalUtil.add(total.getActualProvisionToLastMonth(), salarySummaryVO.getActualProvisionToLastMonth()));
			}
			results.addAll(childGrantSalarySummaryVOS);
		}
        total.setAverageSalary(BigDecimalUtil.divide(total.getLastYearSalary(), total.getActualPeopleNumber(), 4, BigDecimal.ROUND_HALF_UP));
		total.setGrantProgress(BigDecimalUtil.divide(total.getCumulativeGrantAmount(), total.getBudget(), 4, BigDecimal.ROUND_HALF_UP, 100));
		ObjResult objResult = new ObjResult(CommonCode.SUCCESS);
		PageData pd = new PageData();
		pd.put("grantSalarySummaryVO", results);
		objResult.setPageData(pd);
		return objResult;

	}

	@Override
	public ObjResult tree(BaseGrantSalary baseGrantSalary) {
		String fillingMonth = baseGrantSalary.getFillingMonth();
		if (StringUtil.isBlank(fillingMonth)){
			fillingMonth = DateUtil.format(DateUtil.now(), DateUtil.PATTERN_MONTH);
		}

		List<PageData> orgList = orgzationService.getSubordinate().getList();
		if (CollectionUtil.isEmpty(orgList)){
			return new ObjResult(CustomCode.builder().message("企业树初始化失败").code(1999).success(false).build());
		}

		LambdaQueryWrapper<BaseGrantSalary> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(BaseGrantSalary::getFillingMonth, fillingMonth);
		List<BaseGrantSalary> baseGrantSalaries = list(queryWrapper);

		Map<String, List<BaseGrantSalary>> oneMap = new HashMap<>();
		Map<String, List<BaseGrantSalary>> twoMap = new HashMap<>();

		if (CollectionUtil.isNotEmpty(baseGrantSalaries)){
			oneMap = baseGrantSalaries.stream().filter(data -> data.getType() != null && data.getType() == 1)
					.collect(Collectors.groupingBy(BaseGrantSalary::getFillingUnitId));
			twoMap = baseGrantSalaries.stream().filter(data -> data.getType() != null && data.getType() == 2)
					.collect(Collectors.groupingBy(BaseGrantSalary::getFillingUnitId));
		}

		List<GrantSalaryTreeVO> tree = setTree(orgList, oneMap, twoMap);
		GrantSalaryTreeVO result = new GrantSalaryTreeVO();
		if (CollectionUtil.isNotEmpty(tree)){
			result = tree.get(0);
		}
		ObjResult objResult = new ObjResult(CommonCode.SUCCESS);
		PageData pd = new PageData();
		pd.put("tree", result);
		objResult.setPageData(pd);
		return objResult;
	}

	@Override
	public R addTree(BaseGrantSalary baseGrantSalary) {
		String fillingMonth = baseGrantSalary.getFillingMonth();
		if (StringUtil.isBlank(fillingMonth)){
			return new R(CustomCode.builder().message("填报年月为空").code(1999).success(false).build());
		}

		String fillingUnitId = TokenUtil.getTokenOrgId();
		baseGrantSalary.setFillingUnitId(fillingUnitId);
		BaseGrantSalary oneOldBase = getOne(new LambdaQueryWrapper<BaseGrantSalary>()
				.eq(BaseGrantSalary::getFillingUnitId, fillingUnitId)
				.eq(BaseGrantSalary::getFillingMonth, fillingMonth)
				.eq(BaseGrantSalary::getType, 1));

		boolean result = true;
		List<GrantSalary> grantSalaries = new ArrayList<>();
		if (!Optional.ofNullable(oneOldBase).isPresent()){
			baseGrantSalary.setType(1);
			addBaseAndChild(baseGrantSalary, grantSalaries);
		}

		if (orgzationService.isParent(TokenUtil.getTokenOrgId())) {
			BaseGrantSalary twoOldBase = getOne(new LambdaQueryWrapper<BaseGrantSalary>()
					.eq(BaseGrantSalary::getFillingUnitId, fillingUnitId)
					.eq(BaseGrantSalary::getFillingMonth, fillingMonth)
					.eq(BaseGrantSalary::getType, 2));

			if (!Optional.ofNullable(twoOldBase).isPresent()) {
				baseGrantSalary.setType(2);
				addBaseAndChild(baseGrantSalary, grantSalaries);
			}
		}

		if (CollectionUtil.isNotEmpty(grantSalaries)){
			grantSalaryService.saveBatch(grantSalaries);
		}
		return result ? new R(CommonCode.SUCCESS) : new R(CommonCode.FAIL);
	}

	private void addBaseAndChild(BaseGrantSalary baseGrantSalary, List<GrantSalary> grantSalaries){
		BaseGrantSalary twoBase = BaseGrantSalary.builder().fillingMonth(baseGrantSalary.getFillingMonth())
				.fillingUnitId(baseGrantSalary.getFillingUnitId()).type(baseGrantSalary.getType()).build();
		boolean result = this.saveOrUpdate(twoBase);
		HashMap<String, Object> processVariable = new HashMap<>();
		formWorkflowService.startProcessAndSimulate(String.valueOf(twoBase.getId()),twoBase.getFormType(),processVariable);
		R<BaseGrantSalaryVO> lastR = getLastMonthObj(baseGrantSalary);
		if (result){
			List<GrantSalaryVO> grantSalaryVOS = lastR.getPageData().getGrantSalaryVOS();
			for (GrantSalaryVO grantSalaryVO : grantSalaryVOS){
				GrantSalary grantSalary = new GrantSalary();
				BeanUtils.copyProperties(grantSalaryVO, grantSalary);
				grantSalary.setBaseGrantSalaryId(twoBase.getId());
				grantSalaries.add(grantSalary);
				grantSalary.setIsDeleted(0);
				grantSalary.setCreateUser(TokenUtil.getTokenUserId());
				grantSalary.setCreateTime(DateUtil.now());
				grantSalary.setCreateCompanyId(TokenUtil.getTokenOrgId());
			}
		}
	}

	@Override
	public ObjResult childList(BaseGrantSalary baseGrantSalary) {
		String fillingMonth = baseGrantSalary.getFillingMonth();
		if (StringUtil.isBlank(fillingMonth)){
			return new ObjResult(CustomCode.builder().message("填报年月为空").code(1999).success(false).build());
		}
		String fillingUnitId = baseGrantSalary.getFillingUnitId();
		if (StringUtil.isBlank(fillingUnitId)){
			return new ObjResult(CustomCode.builder().message("填报单位为空").code(1999).success(false).build());
		}

		//本级单户表
		List<BaseGrantSalaryVO> results = new ArrayList<>();
		LambdaQueryWrapper<BaseGrantSalary> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(BaseGrantSalary::getFillingMonth, fillingMonth);
		queryWrapper.eq(BaseGrantSalary::getFillingUnitId, fillingUnitId);
		queryWrapper.eq(BaseGrantSalary::getType, 1);
		BaseGrantSalaryVO baseVO = baseGrantSalaryWrapper.entityToVO(getOne(queryWrapper));
		if (Optional.ofNullable(baseVO).isPresent()){
			baseVO.setTypeName("单户表");
			results.add(baseVO);
		}

		//下级合计表和单户表 不包括孙子级
		List<PageData> childList = orgzationService.getChildrenByPId(fillingUnitId);
		if (CollectionUtil.isNotEmpty(childList)){
			List<String> childIds = new ArrayList<>();
			Map<String, String> childOrgMap = new HashMap<>();
			for (PageData child : childList){
				childIds.add((String)child.get("id"));
				childOrgMap.put((String)child.get("id"), (String)child.get("name"));
			}

			List<BaseGrantSalary> childBaseList = list(new LambdaQueryWrapper<BaseGrantSalary>()
					.eq(BaseGrantSalary::getFillingMonth, fillingMonth).in(BaseGrantSalary::getFillingUnitId, childIds));
			if (CollectionUtil.isNotEmpty(childBaseList)){

				// 剔除有合并表数据企业的单表数据
				Map<String, List<BaseGrantSalary>> baseGrantSalaryMap = childBaseList.stream().collect(Collectors.groupingBy(BaseGrantSalary::getFillingUnitId));
				List<Long> delId = new ArrayList<>();
				baseGrantSalaryMap.forEach((k, v) ->{
					if (CollectionUtil.isNotEmpty(v) && v.size() > 1){
						for (BaseGrantSalary child : v){
							if (Optional.ofNullable(child.getType()).isPresent() && child.getType() == 1){
								delId.add(child.getId());
							}
						}
					}
				});

				for (BaseGrantSalary childBase : childBaseList){
					if (!delId.contains(childBase.getId())){
						BaseGrantSalaryVO baseGrantSalaryVO = new BaseGrantSalaryVO();
						baseGrantSalaryVO.setId(childBase.getId());
						baseGrantSalaryVO.setFillingUnitId(childBase.getFillingUnitId());
						baseGrantSalaryVO.setFillingUnitName(childOrgMap.get(childBase.getFillingUnitId()));
						baseGrantSalaryVO.setFillingMonth(childBase.getFillingMonth());
						baseGrantSalaryVO.setType(childBase.getType());
						baseGrantSalaryVO.setStatus(childBase.getStatus());
						if (Optional.ofNullable(childBase.getType()).isPresent()){
							if (childBase.getType() == 1){
								baseGrantSalaryVO.setTypeName("单户表");
							}else if (childBase.getType() == 2){
								baseGrantSalaryVO.setTypeName("集团合并表");
							}
						}
						results.add(baseGrantSalaryVO);
					}
				}
			}
		}

		PageData pd = new PageData();
		pd.put("childList", results);
		ObjResult objResult = new ObjResult(CommonCode.SUCCESS);
		objResult.setPageData(pd);

		return objResult;
	}

	@Override
	public R<BaseGrantSalary> childSummary(BaseGrantSalary baseGrantSalary) {
		List<String> childIds = baseGrantSalary.getChildIds();
		if (CollectionUtil.isEmpty(childIds)){
			return new R(CustomCode.builder().message("未勾选项目").code(1999).success(false).build());
		}

		R<BaseGrantSalary> objResult = new R<>(CommonCode.SUCCESS);
		List<GrantSalaryVO> grantSalaryVOS = grantSalaryMapper.summaryByBaseIds(childIds.stream()
				.map(childId -> Long.valueOf(childId)).collect(Collectors.toList()), TokenUtil.getTokenOrgId());
		setVO(grantSalaryVOS);
		BaseGrantSalaryVO result = new BaseGrantSalaryVO();
		result.setChildIds(childIds);
		result.setGrantSalaryVOS(grantSalaryVOS);
		objResult.setPageData(result);

		return objResult;
	}

	@Override
	public ObjResult summaryDetail(BaseGrantSalaryDTO baseGrantSalaryDTO) {
		ObjResult objResult = new ObjResult(CommonCode.SUCCESS);
		PageData pd = new PageData();
		List<GrantSalarySummaryDetailVO> details =  salarySummaryRelationMapper.summaryDetail(baseGrantSalaryDTO.getBaseGrantSalaryId(),
				baseGrantSalaryDTO.getCountCategoryId(), baseGrantSalaryDTO.getColumnName());
		if (CollectionUtil.isNotEmpty(details)){
			for (GrantSalarySummaryDetailVO vo : details){
				if (Optional.ofNullable(vo.getType()).isPresent()){
					if (vo.getType() == 1){
						vo.setTypeName("单户表");
					}else if (vo.getType() == 2){
						vo.setTypeName("集团合并表");
					}
				}
			}
		}
		pd.put("details", details);
		objResult.setPageData(pd);
		return objResult;
	}

	/**
	 * 计算比例
	 * @param grantSalaryVOS
	 */
	private void setVO(List<GrantSalaryVO> grantSalaryVOS){
		if (CollectionUtil.isNotEmpty(grantSalaryVOS)){
			Map<String, String> countCategoryMap = baseInfoService.getChildMap(ValueSetConstant.SALARY_COUNT_CATEGORY);
			for (GrantSalaryVO grantSalaryVO : grantSalaryVOS){
				grantSalaryVO.setCountCategoryName(countCategoryMap.get(grantSalaryVO.getCountCategoryId()));
				grantSalaryVO.setGrantProgress(BigDecimalUtil.divide(grantSalaryVO.getCumulativeGrantAmount(),
						grantSalaryVO.getBudget(), 2, BigDecimal.ROUND_HALF_UP));
				grantSalaryVO.setAverageSalary(BigDecimalUtil.divide(grantSalaryVO.getLastYearSalary(),
						grantSalaryVO.getActualPeopleNumber(), 2, BigDecimal.ROUND_HALF_UP));
			}
		}
	}

	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public R initAdd(BaseGrantSalary baseGrantSalary) {
		BaseGrantSalary old = getOne(new LambdaQueryWrapper<BaseGrantSalary>()
				.eq(BaseGrantSalary::getFillingUnitId, TokenUtil.getTokenOrgId())
				.eq(BaseGrantSalary::getFillingMonth, baseGrantSalary.getFillingMonth()));
		if (Optional.ofNullable(old).isPresent()){
			return new R(CustomCode.builder().message("该年月已填报").code(1999).success(false).build());
		}

		R<BaseGrantSalaryVO> lastR = getLastMonthObj(baseGrantSalary);
		if (!lastR.isSuccess()){
			return lastR;
		}

		BaseGrantSalary init = new BaseGrantSalary();
		init.setFillingMonth(baseGrantSalary.getFillingMonth());
		init.setFillingUnitId(TokenUtil.getTokenOrgId());
		boolean result = saveOrUpdate(init);
		if (result){
			List<GrantSalaryVO> grantSalaryVOS = lastR.getPageData().getGrantSalaryVOS();
			for (GrantSalaryVO grantSalaryVO : grantSalaryVOS){
				GrantSalary grantSalary = new GrantSalary();
				BeanUtils.copyProperties(grantSalaryVO, grantSalary);
				grantSalary.setBaseGrantSalaryId(init.getId());
				grantSalaryService.saveOrUpdate(grantSalary);
			}
		}

		return R.status(result);
	}

	/**
	 * 递归 树的初始化
	 * @param orgList
	 * @param oneMap
	 * @param twoMap
	 * @return
	 */
	private List<GrantSalaryTreeVO> setTree(List<PageData> orgList, Map<String, List<BaseGrantSalary>> oneMap, Map<String, List<BaseGrantSalary>> twoMap){
		List<GrantSalaryTreeVO> tree = new ArrayList<>();
		for (PageData org : orgList){
			List<PageData> orgChildren = (List<PageData>)org.get("children");
			String fillingUnitId = (String)org.get("id");
			String fillingUnitName = (String)org.get("name");
			String orgCode =  (String)org.get("orgCode");
			String orgType = org.getString("type");
			BaseGrantSalary oneBase = new BaseGrantSalary();
			if (oneMap.containsKey(fillingUnitId)){
				oneBase = oneMap.get(fillingUnitId).get(0);
			}
			if (CollectionUtil.isNotEmpty(orgChildren)){
				GrantSalaryTreeVO result = GrantSalaryTreeVO.builder().fillingUnitId(fillingUnitId)
						.status(FormStatusConstant.NOFILLING)
						.fillingUnitName(fillingUnitName).type(3).build();
				List<GrantSalaryTreeVO> children = new ArrayList<>();
				//判断该单位是否为集团和下级
//				if (StringUtil.isNotBlank(orgCode) && "2".equals(orgType)){ //去掉判断这样国资委的也可以用了
					result.setType(2);
					result.setTypeName("集团合并表");
					//自己节点为合计表
					if (twoMap.containsKey(fillingUnitId)){
						BaseGrantSalary twoBase = twoMap.get(fillingUnitId).get(0);
						result.setStatus(twoBase.getStatus());
						result.setFillingMonth(twoBase.getFillingMonth());
						result.setFormType(String.valueOf(FormTypeConstant.PF_BASE_WELFARE_EXPEND));
						result.setBaseGrantSalaryId(twoBase.getId());
					}
					//子节点第一个为 单表
					GrantSalaryTreeVO child = GrantSalaryTreeVO.builder().fillingUnitId(fillingUnitId).fillingUnitName(fillingUnitName)
							.fillingMonth(oneBase.getFillingMonth()).baseGrantSalaryId(oneBase.getId()).status(oneBase.getStatus())
							.formType(String.valueOf(FormTypeConstant.PF_BASE_WELFARE_EXPEND)).typeName("单户表").type(1)
							.build();
					if (child.getStatus() == null){
						child.setStatus(FormStatusConstant.NOFILLING);
					}
					children.add(child);
//				}

				tree.add(result);
				children.addAll(setTree(orgChildren, oneMap, twoMap));
				result.setChildren(children);
			}else {
				//自己节点为 单表
				GrantSalaryTreeVO result = GrantSalaryTreeVO.builder().fillingUnitId(fillingUnitId).fillingUnitName(fillingUnitName)
						.fillingMonth(oneBase.getFillingMonth()).typeName("单户表")
						.formType(String.valueOf(FormTypeConstant.PF_BASE_WELFARE_EXPEND))
						.baseGrantSalaryId(oneBase.getId()).type(1).status(oneBase.getStatus())
						.build();
				if (result.getStatus() == null){
					result.setStatus(FormStatusConstant.NOFILLING);
				}
				tree.add(result);
			}
		}
		return tree;
	}

	/**
	 * 集团数据
	 * @param fillingUnitId
	 * @param fillingUnitName
	 * @param grantSalaries
	 * @return
	 */
	private List<GrantSalarySummaryVO> firstSet(String fillingUnitId, String fillingUnitName, List<GrantSalary> grantSalaries){
		Map<String, String> countCategoryMap = baseInfoService.getChildMap(ValueSetConstant.SALARY_COUNT_CATEGORY);
		List<GrantSalarySummaryVO> firstResults = new ArrayList<>();
		if (CollectionUtil.isNotEmpty(grantSalaries)){
			for (GrantSalary grantSalary : grantSalaries){
				GrantSalarySummaryVO result = new GrantSalarySummaryVO();
				BeanUtils.copyProperties(grantSalary, result);
				result.setCountCategoryName(countCategoryMap.get(result.getCountCategoryId()));
				result.setFillingUnitId(fillingUnitId);
				result.setFillingUnitName(fillingUnitName);
				firstResults.add(result);
			}
		}else {
			countCategoryMap.forEach((k,v) ->{
				GrantSalarySummaryVO result = GrantSalarySummaryVO.builder().countCategoryId(k).countCategoryName(v)
						.fillingUnitId(fillingUnitId).fillingUnitName(fillingUnitName).build();
				firstResults.add(result);
			});
		}
		Collections.sort(firstResults, (a, b) -> Integer.valueOf(a.getCountCategoryId()).compareTo(Integer.valueOf(b.getCountCategoryId())));
		return firstResults;
	}

	/**
	 * 子企业数据
	 * @param childIds
	 * @param baseChildMap baseChildGrantSalaryId, fillingUnitId
	 * @param childGrantSalaryMap baseChildGrantSalaryId, List<ChildGrantSalary
	 * @return
	 */
	private List<GrantSalarySummaryVO> childSet(List<String> childIds, Map<String, Long> baseChildMap,  Map<Long, List<ChildGrantSalary>> childGrantSalaryMap){

		List<PageData> pageDataList = (List<PageData>) orgzationService.listAll().getPageData().get("list");
		HashMap<String, String> orgMap = new HashMap<>();
		if (CollectionUtil.isNotEmpty(pageDataList)){
			for (PageData pd : pageDataList){
				orgMap.put((String)pd.get("id"), (String)pd.get("name"));
			}
		}
		List<GrantSalarySummaryVO> childResults = new ArrayList<>();
		Map<String, String> childCountCategoryMap = baseInfoService.getChildMap(ValueSetConstant.CHILD_SALARY_COUNT_CATEGORY);
		// 合计数组
		List<GrantSalarySummaryVO> endResults = initChildEndSummary(childCountCategoryMap);
		childResults.addAll(endResults);
		if (CollectionUtil.isNotEmpty(childIds)){

			for (String childId : childIds){
				List<GrantSalarySummaryVO> tempList = new ArrayList<>();
				if (CollectionUtil.isNotEmpty(baseChildMap) && baseChildMap.containsKey(childId)){
					List<ChildGrantSalary> childGrantSalaries = childGrantSalaryMap.get(baseChildMap.get(childId));
					for (ChildGrantSalary childGrantSalary : childGrantSalaries){
						GrantSalarySummaryVO result = new GrantSalarySummaryVO();
						BeanUtils.copyProperties(childGrantSalary, result);
						result.setCountCategoryId(childGrantSalary.getChildCountCategoryId());
						if ("086001".equals(result.getCountCategoryId())){
							result.setCountCategoryName(orgMap.get(childId));
							if (!orgMap.containsKey(childId)){
								log.error("BaseGrantSalaryServiceImpl  childSet方法 获取企业名称失败-------------->" + orgMap);
								log.error("BaseGrantSalaryServiceImpl  childSet方法 获取企业名称失败-------------->" + childId);
							}
						}else {
							result.setCountCategoryName(childCountCategoryMap.get(result.getCountCategoryId()));
						}

						result.setFillingUnitId(childId);
						result.setFillingUnitName(orgMap.get(childId));
						tempList.add(result);

						for (GrantSalarySummaryVO end : endResults){
							if (end.getCountCategoryId().equals(childGrantSalary.getChildCountCategoryId())){
								end.setOnJobNumber(BigDecimalUtil.add(end.getOnJobNumber(), childGrantSalary.getOnJobNumber()));
								end.setCumulativeGrantAmount(BigDecimalUtil.add(end.getCumulativeGrantAmount(), childGrantSalary.getCumulativeGrantAmount()));
								end.setActualGrantAmount(BigDecimalUtil.add(end.getActualGrantAmount(), childGrantSalary.getActualGrantAmount()));
								end.setBudget(BigDecimalUtil.add(end.getBudget(), childGrantSalary.getBudget()));
								end.setLastYearSalary(BigDecimalUtil.add(end.getLastYearSalary(), childGrantSalary.getLastYearSalary()));
								end.setActualPeopleNumber(BigDecimalUtil.add(end.getActualPeopleNumber(), childGrantSalary.getActualPeopleNumber()));
								end.setLastCumulativeGrantAmount(BigDecimalUtil.add(end.getLastCumulativeGrantAmount(), childGrantSalary.getLastCumulativeGrantAmount()));

								end.setCumulativeProvisionThisYear(BigDecimalUtil.add(end.getCumulativeProvisionThisYear(), childGrantSalary.getCumulativeProvisionThisYear()));
								end.setActualProvisionThisMonth(BigDecimalUtil.add(end.getActualProvisionThisMonth(), childGrantSalary.getActualProvisionThisMonth()));
								end.setActualProvisionLastYear(BigDecimalUtil.add(end.getActualProvisionLastYear(), childGrantSalary.getActualProvisionLastYear()));
								end.setActualProvisionToLastMonth(BigDecimalUtil.add(end.getActualProvisionToLastMonth(), childGrantSalary.getActualProvisionToLastMonth()));
								break;
							}
						}
					}
				}else {
					childCountCategoryMap.forEach((k,v) ->{
						GrantSalarySummaryVO result = GrantSalarySummaryVO.builder().countCategoryId(k).countCategoryName(v)
								.fillingUnitId(childId).fillingUnitName(orgMap.get(childId)).build();
						if ("086001".equals(k)){
							result.setCountCategoryName(orgMap.get(childId));
                            if (!orgMap.containsKey(childId)){
								log.error("BaseGrantSalaryServiceImpl  childSet方法 获取企业名称失败-------------->" + orgMap);
                                log.error("BaseGrantSalaryServiceImpl  childSet方法 获取企业名称失败-------------->" + childId);
                            }
						}
						tempList.add(result);
					});
				}
				Collections.sort(tempList, (a, b) -> Integer.valueOf(a.getCountCategoryId()).compareTo(Integer.valueOf(b.getCountCategoryId())));
				childResults.addAll(tempList);
			}
			for (GrantSalarySummaryVO end : endResults){
                end.setAverageSalary(BigDecimalUtil.divide(end.getLastYearSalary(), end.getActualPeopleNumber(), 4, BigDecimal.ROUND_HALF_UP));
				end.setGrantProgress(BigDecimalUtil.divide(end.getCumulativeGrantAmount(), end.getBudget(), 4, BigDecimal.ROUND_HALF_UP, 100));
			}
		}

		return childResults;

	}

	private List<GrantSalarySummaryVO> initChildEndSummary(Map<String, String> childCountCategoryMap){
		List<GrantSalarySummaryVO> initList = new ArrayList<>();
		childCountCategoryMap.forEach((k,v) ->{
			GrantSalarySummaryVO init = GrantSalarySummaryVO.builder().countCategoryId(k).countCategoryName(v).build();
					initList.add(init);
				}
		);
		Collections.sort(initList, (a, b) -> Integer.valueOf(a.getCountCategoryId()).compareTo(Integer.valueOf(b.getCountCategoryId())));
		for (int i = 0; i < 3; i++){
			GrantSalarySummaryVO init = initList.get(i);
			switch (i){
				case 0:
					init.setCountCategoryName("子企业工资总额");
					break;
				case 1:
					init.setCountCategoryName("① 子企业负责人小计");
					break;
				case 2:
					init.setCountCategoryName("② 子企业职业经理人小计");
					break;
			}
		}
		return initList;
	}

	/**
	 * 获取子企业单位id  不包含孙子级
	 * @param tokenOrgId
	 * @return
	 */
	private List<String> getChildIds(String tokenOrgId){
		List<PageData> childList = orgzationService.getChildrenByPId(tokenOrgId);
		if (CollectionUtil.isEmpty(childList)){
			return new ArrayList<>();
		}
		List<String> childIds = new ArrayList<>();
		for (PageData child : childList){
			childIds.add((String)child.get("id"));
		}
		return childIds;
	}
	/**
	 * 获取集团树列表
	 * @param query
	 * @param queryWrapper
	 * @param listResult
	 * @param pageDataList
	 * @param tokenOrgId
	 * @return
	 */
	private void getFirstTree(Query query, QueryWrapper<BaseChildGrantSalary> queryWrapper, ListResult<PageData> listResult,
							  List<PageData> pageDataList, String tokenOrgId){
		List<String> childIds = getChildIds(tokenOrgId);
		if (CollectionUtil.isEmpty(childIds)){
			listResult.setTotal(0);
			return;
		}
		queryWrapper.in("filling_unit_id", childIds);

		// 子企业填报数据
		List<String> childMonthList = baseChildGrantSalaryService.list(queryWrapper)
				.stream().map(BaseChildGrantSalary::getFillingMonth).collect(Collectors.toList());
		//集团填报数据
		List<String> monthList = list(new QueryWrapper<BaseGrantSalary>().eq("filling_unit_id", tokenOrgId).orderByDesc("filling_month"))
				.stream().map(BaseGrantSalary::getFillingMonth).collect(Collectors.toList());

		//根据月份生成 树列表
		List<String> existMonthList = new ArrayList<>();
		if (CollectionUtil.isNotEmpty(monthList)){
			for (String month : monthList){
				if (!existMonthList.contains(month)){
					existMonthList.add(month);
				}
			}
		}

		if (CollectionUtil.isNotEmpty(childMonthList)){
			for (String month : childMonthList){
				if (!existMonthList.contains(month)){
					existMonthList.add(month);
				}
			}
		}
		listResult.setTotal(existMonthList.size());
		List<String> resultMonthList = new ArrayList<>();

		if (CollectionUtil.isNotEmpty(existMonthList)) {
			Collections.sort(existMonthList, (a, b) -> Long.valueOf(DateUtil.parse(b, DateUtil.PATTERN_MONTH).getTime())
					.compareTo(Long.valueOf(DateUtil.parse(a, DateUtil.PATTERN_MONTH).getTime())));

			//分页
			int startIndex = query.getPageSize() * (query.getPageNumber() - 1);
			int endIndex = query.getPageSize() * query.getPageNumber() - 1;
			if (endIndex > existMonthList.size() - 1) {
				endIndex = existMonthList.size() - 1;
			}
			if (startIndex > endIndex) {
				startIndex = endIndex;
			}
			for (int i = startIndex; i <= endIndex; i++) {
				resultMonthList.add(existMonthList.get(i));
			}

			PageData org = orgzationService.getCompanyNameById(tokenOrgId);
			String fillingUnitName = "";
			if (org != null) {
				fillingUnitName = org.getString("name");
			}
			for (String month : resultMonthList) {
				PageData pd = new PageData();
				pd.put("fillingUnitId", tokenOrgId);
				pd.put("fillingUnitName", fillingUnitName);
				pd.put("fillingMonth", month);
				pd.put("typeName", "集团合并表");
				pd.put("type", 2);
				pageDataList.add(pd);
			}
		}

	}

	private boolean checkIsFirst(String orgId){
		PageData p = new PageData();
		p.put("id", orgId);
		PageData tokenOrg = orgzationService.findbyid(p).getPageData();
		if (Optional.ofNullable(tokenOrg).isPresent()){
			String orgCode = (String)tokenOrg.get("orgCode");
			return StringUtil.isNotBlank(orgCode) && orgCode.length() == 8;
		}
		return false;
	}


	/**
	 * 按月赋值
	 * @param grantSalary
	 * @param result
	 * @param fillingMonth
	 */
	private void setValue(GrantSalary grantSalary, SalaryMonthStatisticsVO result, String fillingMonth){
		int month = Integer.valueOf(fillingMonth.split("-")[1]);
		switch (month){
			case 1:
				result.setJanuaryOnJobNumber(grantSalary.getOnJobNumber());
				result.setJanuaryActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 2:
				result.setFebruaryOnJobNumber(grantSalary.getOnJobNumber());
				result.setFebruaryActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 3:
				result.setMarchOnJobNumber(grantSalary.getOnJobNumber());
				result.setMarchActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 4:
				result.setAprilOnJobNumber(grantSalary.getOnJobNumber());
				result.setAprilActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 5:
				result.setMayOnJobNumber(grantSalary.getOnJobNumber());
				result.setMayActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 6:
				result.setJuneOnJobNumber(grantSalary.getOnJobNumber());
				result.setJuneActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 7:
				result.setJulyOnJobNumber(grantSalary.getOnJobNumber());
				result.setJulyActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 8:
				result.setAugustOnJobNumber(grantSalary.getOnJobNumber());
				result.setAugustActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 9:
				result.setSeptemberOnJobNumber(grantSalary.getOnJobNumber());
				result.setSeptemberActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 10:
				result.setOctoberOnJobNumber(grantSalary.getOnJobNumber());
				result.setOctoberActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 11:
				result.setNovemberOnJobNumber(grantSalary.getOnJobNumber());
				result.setNovemberActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 12:
				result.setDecemberOnJobNumber(grantSalary.getOnJobNumber());
				result.setDecemberActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			default:
				break;

		}
	}

	private List<SalaryMonthStatisticsVO> initSummary(Integer type, String fillingUnitName){
		Map<String, String> countCategoryMap = baseInfoService.getChildMap(ValueSetConstant.SALARY_COUNT_CATEGORY);
		List<SalaryMonthStatisticsVO> initList = new ArrayList<>();
		countCategoryMap.forEach((k,v) ->{
			SalaryMonthStatisticsVO init = SalaryMonthStatisticsVO.builder().countCategoryId(k).countCategoryName(v)
					.fillingUnitName(fillingUnitName).statisticsType(type).build();
//			if ("085002".equals(k)|| "085006".equals(k)){
//				if (type == 1){
//					init.setCountCategoryName("本部" + init.getCountCategoryName());
//				}else if (type == 2){
//					init.setCountCategoryName("汇总" + init.getCountCategoryName());
//				}
//			}
			initList.add(init);
		});
		Collections.sort(initList, (a, b) -> Integer.valueOf(a.getCountCategoryId()).compareTo(Integer.valueOf(b.getCountCategoryId())));
		return initList;
	}

	/**
	 * 初始化列表
	 * @param grantSalaryVOS
	 * @return
	 */
	private List<GrantSalaryVO> init(List<GrantSalaryVO> grantSalaryVOS, String fillingYear, List<String> fillingUnitIds,
									 List<GrantSalary> grantSalaries, Integer type, boolean isUnit){
		Map<String, String> countCategoryMap = baseInfoService.getChildMap(ValueSetConstant.SALARY_COUNT_CATEGORY);
		List<GrantSalaryVO> initList = new ArrayList<>();
		countCategoryMap.forEach((k,v) ->{
			GrantSalaryVO init = new GrantSalaryVO();
			if (!isUnit && "085006".equals(k)){
				return;
			}
			init.setCountCategoryId(k);
			init.setCountCategoryName(v);

			if (CollectionUtil.isNotEmpty(grantSalaryVOS)){
				//上月已填报情况
				for (GrantSalaryVO grantSalaryVO : grantSalaryVOS){
					if (k.equals(grantSalaryVO.getCountCategoryId())){
						init.setBudget(grantSalaryVO.getBudget());
						init.setActualGrantAmount(grantSalaryVO.getActualGrantAmount());
						init.setCumulativeGrantAmount(BigDecimalUtil.add(grantSalaryVO.getCumulativeGrantAmount(), grantSalaryVO.getActualGrantAmount()));
						init.setLastCumulativeGrantAmount(grantSalaryVO.getCumulativeGrantAmount());
						init.setOnJobLastTotalNumber(grantSalaryVO.getOnJobTotalNumber());
						init.setOnJobTotalNumber(BigDecimalUtil.add(grantSalaryVO.getOnJobTotalNumber(), grantSalaryVO.getOnJobNumber()));
						init.setOnJobNumber(grantSalaryVO.getOnJobNumber());
						init.setAverageSalary(grantSalaryVO.getAverageSalary());
						init.setActualPeopleNumber(grantSalaryVO.getActualPeopleNumber());
						init.setArtificialCost(grantSalaryVO.getArtificialCost());
						init.setLastYearSalary(grantSalaryVO.getLastYearSalary());
						init.setLastArtificialCost(grantSalaryVO.getCumulativeArtificialCost());
						init.setCumulativeArtificialCost(BigDecimalUtil.add(grantSalaryVO.getCumulativeArtificialCost(), grantSalaryVO.getArtificialCost()));
						init.setGrantProgress(BigDecimalUtil.divide(init.getCumulativeGrantAmount(),
								init.getBudget(), 2, BigDecimal.ROUND_HALF_UP, 100));

						init.setActualProvisionThisMonth(grantSalaryVO.getActualProvisionThisMonth());
						init.setCumulativeProvisionThisYear(BigDecimalUtil.add(grantSalaryVO.getCumulativeProvisionThisYear(), grantSalaryVO.getActualProvisionThisMonth()));
						init.setActualProvisionLastYear(grantSalaryVO.getActualProvisionLastYear());
						init.setActualProvisionToLastMonth(grantSalaryVO.getCumulativeProvisionThisYear());
						break;
					}
				}
			}else if(CollectionUtil.isNotEmpty(grantSalaries)){
				//上月未填报，但本年有填报数据情况
				for (GrantSalary grantSalary : grantSalaries) {
					if (k.equals(grantSalary.getCountCategoryId())) {
						init.setBudget(grantSalary.getBudget());
						init.setAverageSalary(grantSalary.getAverageSalary());
						init.setActualPeopleNumber(grantSalary.getActualPeopleNumber());
						init.setLastYearSalary(grantSalary.getLastYearSalary());
						break;
					}
				}
			}
			initList.add(init);
		});
		Collections.sort(initList, (a, b) -> Integer.valueOf(a.getCountCategoryId()).compareTo(Integer.valueOf(b.getCountCategoryId())));
		if (CollectionUtil.isEmpty(grantSalaryVOS) && CollectionUtil.isEmpty(grantSalaries) ){
			//没有填报数据 填充去年统计数据
			lastInit(initList, getList(fillingYear, fillingUnitIds, type));
		}
		return initList;
	}

	private void lastInit(List<GrantSalaryVO> initList, List<SalaryMonthStatisticsVO> salaryMonthStatisticsVOS){
		for (int i = 0; i<initList.size(); i++){
			initList.get(i).setAverageSalary(salaryMonthStatisticsVOS.get(i).getAverageSalary());
			initList.get(i).setActualPeopleNumber(salaryMonthStatisticsVOS.get(i).getYearAverage());
			initList.get(i).setLastYearSalary(salaryMonthStatisticsVOS.get(i).getTotalActualGrantAmount());
		}
	}

	@Override
	public void exportExcel(PageData pd, HttpServletResponse response, OutputStream os)  {
		try {
			String fname = "职工工资发放管理导出表";
			os = response.getOutputStream();//取得输出流
			response.reset();//清空输出流
			//下面是对中文文件名的处理
			response.setCharacterEncoding("UTF-8");//设置相应内容的编码格式
			//读取系统中的模板
			InputStream inputStream = this.getClass().getResourceAsStream("/exceldemo/SalaryPayment.xlsx");
			//InputStream inputStream = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\SalaryPayment.xlsx"));
			fname = java.net.URLEncoder.encode(fname, "UTF-8");
			response.setHeader("Content-Disposition", "attachment;filename=" + new String(fname.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8) + ".xls");
			response.setContentType("application/msexcel");//定义输出类型
			//年月: 职工福利费支出明细表（xxxx年xx月）
			String fillingMonth = pd.getString("fillingMonth");
			String[] split = fillingMonth.split("-");
			fillingMonth = "职工工资发放表-统计用("+split[1]+"月度)";
			//企业名称:企业名称：xxxx
			String fillingUnitName = pd.getString("fillingUnitName");
			String name = "企业制表人：                                                                                          审计人员：                                                                   填报日期："+split[0]+"年"+split[1]+"月";
			fillingUnitName = "企业名称："+fillingUnitName;
			List<HashMap> grantSalaryVOS = (List<HashMap>) pd.get("grantSalaryVOS");
			//多少行
			int row = grantSalaryVOS.size();
			//克隆模板得到一个新的excel模板
			DynamicOperateExcelUtils dynamicOperateExcelUtils = new DynamicOperateExcelUtils(inputStream);
			//获取工作簿
			Workbook workbook = dynamicOperateExcelUtils.getWorkbook();
			//获取表格
			Sheet sheet = dynamicOperateExcelUtils.getSheet(2);
			dynamicOperateExcelUtils.replaceCellValue(1, 0, fillingMonth);
			dynamicOperateExcelUtils.replaceCellValue(2, 0, fillingUnitName);
			dynamicOperateExcelUtils.replaceCellValue(11, 0, name);
			for (int a = 0; a < row; a++) {
				HashMap welfareExpendVO = grantSalaryVOS.get(a);
				//非增行的替换模板单元格的数据
				for (int b = 0; b < 12; b++) {
					switch (b){
						case 0: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("countCategoryName"));break;
						case 1: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("onJobNumber"));break;
						case 2: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("actualGrantAmount"));break;
						case 3: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("cumulativeGrantAmount"));break;
						case 4: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("budget"));break;
						case 5: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("grantProgress"));break;//grantProgress
						case 6: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("lastYearSalary"));break;
						case 7: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("actualPeopleNumber"));break;
						case 8: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("averageSalary"));break;
						case 9: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("artificialCost"));break;
						case 10: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("cumulativeArtificialCost"));break;
						case 11: dynamicOperateExcelUtils.replaceCellValue(a + 6, b, welfareExpendVO.get("remark"));break;
						default:break;
					}
				}
			}
			workbook.removeSheetAt(0);
			workbook.removeSheetAt(0);
			//dynamicOperateExcelUtils.exportExcel("D:\\职工工资发放管理导出表.xlsx");
			workbook.write(os);
			os.flush();
			os.close();
			workbook.close();
		} catch (IOException e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
	}


	/**
	 * 职工工资发放
	 * @param propertyTime
	 * @return
	 */
	@Override
	public List<PageData> findGrantSalaryListByCreate(PropertyTime propertyTime){
		List<PageData> listByDateRange = new ArrayList<>();
		try {
			PageData pageData = new PageData();
			pageData.put("startTime",propertyTime.getStartTime());
			pageData.put("endTime",propertyTime.getEndTime());
			List<PageData> pageDataList = grantSalaryMapper.grantSalaryByCreat(pageData);
			HashMap<String, PageData> map = pdlistToMap(pageDataList);
			listByDateRange = mapAddPdlist(map, listByDateRange);
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
		return listByDateRange;
	}

	@Override
	public List<PageData> findGrantSalaryListByUpdate(PropertyTime propertyTime){
		List<PageData> listByDateRange = new ArrayList<>();
		try {
			PageData pageData = new PageData();
			pageData.put("startTime",propertyTime.getStartTime());
			pageData.put("endTime",propertyTime.getEndTime());
			List<PageData> pageDataList = grantSalaryMapper.grantSalaryByUpdate(pageData);
			HashMap<String, PageData> map = pdlistToMap(pageDataList);
			listByDateRange = mapAddPdlist(map, listByDateRange);
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
		return listByDateRange;
	}

//	@Override TODO DEL
//	public List<SalaryWarningVO> getSalaryWarning(BaseGrantSalaryDTO baseGrantSalaryDTO) {
//		String orgId = TokenUtil.getTokenOrgId();
//		BigDecimal yellowLine = new BigDecimal(100);
//		BigDecimal redLine = new BigDecimal(environment.getProperty("salary.red-line"));
//		List<String> fillingUnitIds = new ArrayList<>();
//		if (orgzationService.checkGzwName(orgId)){
//			try {
//				fillingUnitIds.addAll(Optional.ofNullable(orgzationDao.findGZWUnits()).orElse(new ArrayList<>())
//						.stream().map(p -> p.getString("id")).collect(Collectors.toList()));
//			}catch (Exception e){
//				log.error("getSalaryWarning----> 获取集团单位id失败");
//				log.error(ExceptionUtils.getFullStackTrace(e));
//			}
//		}else {
//			fillingUnitIds.add(orgId);
//		}
//
//		List<SalaryWarningVO> list = baseMapper.getSalaryWarning(fillingUnitIds, baseGrantSalaryDTO.getFillingYear());
//		for (SalaryWarningVO salaryWarningVO : list){
//			salaryWarningVO.setOctColor(findColor(yellowLine, redLine, salaryWarningVO.getOctBudget(), salaryWarningVO.getOctGrantAmount()));
//			salaryWarningVO.setNovColor(findColor(yellowLine, redLine, salaryWarningVO.getNovBudget(), salaryWarningVO.getNovGrantAmount()));
//			salaryWarningVO.setDecColor(findColor(yellowLine, redLine, salaryWarningVO.getDecBudget(), salaryWarningVO.getDecGrantAmount()));
//		}
//		return list;
//	}

	@Override
	public List<Message> getWarningMessage() {
		List<String> fillingUnitIds = new ArrayList<>();
		try{
			List<UserRoleInfoVO> userList = userDao.findSalaryWaringUser();
			if (CollectionUtil.isEmpty(userList)){
				log.info("getWarningMessage--->未找到用户");
				return null;
			}

			List<PageData> units = orgzationDao.findGZWUnits();
			if (CollectionUtil.isEmpty(units)){
				log.info("getWarningMessage--->未找到集团");
				return null;
			}

			Map<String, String> orgIdNameMap = units.stream().collect(Collectors.toMap(unit -> unit.getString("id"), unit -> unit.getString("name")));
			fillingUnitIds.addAll(units.stream().map(p -> p.getString("id")).collect(Collectors.toList()));
			List<String> fillingMonthList = Stream.of("10","11","12").collect(Collectors.toList());

			List<BaseGrantSalary> baseGrantSalaryList = list(new QueryWrapper<BaseGrantSalary>().eq("type", 2)
					.eq("status", FormStatusConstant.FINISH).in("filling_unit_id", fillingUnitIds));
			baseGrantSalaryList = Optional.ofNullable(baseGrantSalaryList).orElse(new ArrayList<>()).stream()
					.filter(baseGrantSalary -> fillingMonthList.contains(baseGrantSalary.getFillingMonth().split("-")[1]))
					.collect(Collectors.toList());
			if (CollectionUtil.isEmpty(baseGrantSalaryList)){
				return null;
			}

			List<GrantSalary> grantSalaryList = grantSalaryService.list(new LambdaQueryWrapper<GrantSalary>().eq(GrantSalary::getCountCategoryId, "085002")
					.in(GrantSalary::getBaseGrantSalaryId, baseGrantSalaryList.stream().map(BaseGrantSalary::getId).collect(Collectors.toList())));
			if (CollectionUtil.isEmpty(grantSalaryList)){
				return null;
			}

			Map<Long, BaseGrantSalary> baseMap = baseGrantSalaryList.stream().collect(Collectors.toMap(BaseGrantSalary::getId, baseGrantSalary -> baseGrantSalary));
			List<PageData> gzwOrgs = orgzationDao.findByName(gzwProperties.getName());
			String gzwId = "";
			if (CollectionUtil.isNotEmpty(gzwOrgs)){
				gzwId =gzwOrgs.get(0).getString("id");
			}

			Map<String, List<String>> orgUserMap = orgUserMap(fillingUnitIds, gzwId, userList);
			BigDecimal redLine = new BigDecimal(environment.getProperty("salary.red-line"));

			List<Message> messages = new ArrayList<>();
			List<String> noCheckFormIds = ignoreMessageInfoService.list(Wrappers.<IgnoreMessageInfo>lambdaQuery()
							.eq(IgnoreMessageInfo::getFormType, FormTypeConstant.CQZC_BONDISSUE)).stream()
					.filter(ignoreMessageInfo -> StringUtil.isNotBlank(ignoreMessageInfo.getFormId()))
					.map(IgnoreMessageInfo::getFormId).collect(Collectors.toList());
			for (GrantSalary grantSalary : grantSalaryList){
				BigDecimal bigDecimal = BigDecimalUtil.divide(grantSalary.getCumulativeGrantAmount(), grantSalary.getBudget(),
						BigDecimal.ROUND_HALF_UP, 2, 100);
				if (noCheckFormIds.contains(grantSalary.getBaseGrantSalaryId())){
					continue;
				}
				if (bigDecimal != null && bigDecimal.compareTo(redLine) == 1){
					BaseGrantSalary baseGrantSalary = baseMap.get(grantSalary.getBaseGrantSalaryId());

					List<String> userOrgIds = orgUserMap.get(baseGrantSalary.getFillingUnitId());
					if (CollectionUtil.isNotEmpty(userOrgIds)){
						for(String userOrgId : userOrgIds){
							String orgId = userOrgId.split("-")[0];
							String userId = userOrgId.split("-")[1];
							Message message = Message.builder().createUser(userId)
									.formId(String.valueOf(baseGrantSalary.getId())).formTypeName("职工工资发放管理")
									.formType("salaryWarning")
									.orgId(orgId)
									.orgName(orgIdNameMap.get(baseGrantSalary.getFillingUnitId()))
									.messageTime(DateUtil.now())
									.message(baseGrantSalary.getFillingMonth() + "工资超过预警线")
									.build();
							messages.add(message);
						}
					}
				}
			}
			return messages;

		}catch (Exception e){
			log.error("getWarningMessage----> 获取集团单位id失败");
			log.error(ExceptionUtils.getFullStackTrace(e));
		}

		return null;
	}

	private Map<String, List<String>> orgUserMap(List<String> unitIds, String gzwId, List<UserRoleInfoVO> userList){
		Map<String, List<String>> map = new HashMap<>(unitIds.size());
		for (String unitId : unitIds){
			map.put(unitId, new ArrayList<>());
		}

		for (UserRoleInfoVO userRoleInfoVO : userList){
			String orgId = userRoleInfoVO.getOrgId();
			String userId = userRoleInfoVO.getUserId();
			String value = orgId + StringPool.DASH + userId;
			if (gzwId.equals(orgId)){
				map.forEach((k, v) -> {
					v.add(value);
				});
			}

			if (unitIds.contains(orgId)){
				List<String> userIds = map.get(orgId);
				userIds.add(value);
			}
		}
		return map;
	}

	private String findColor(BigDecimal yellowLine, BigDecimal redLine, BigDecimal budget, BigDecimal grantAmount){
		BigDecimal bigDecimal = BigDecimalUtil.divide(grantAmount, budget, BigDecimal.ROUND_HALF_UP, 2, 100);
		if (bigDecimal == null || bigDecimal.compareTo(yellowLine) < 1){
			return "#448800";
		}

		if (bigDecimal.compareTo(redLine) == 1){
			return "#db1809";
		}

		return "#bfba50";
	}


	public  HashMap<String, PageData> pdlistToMap(List<PageData> pageDataList){
		HashMap<String, PageData> map = new HashMap<>();
		for (PageData vo:pageDataList){
			String id = vo.getString("id");
			String fillingUnitId = vo.getString("fillingUnitId");
			String fillingMonth = vo.getString("fillingMonth");
			String key = id +"\t"+fillingUnitId+"\t"+fillingMonth;
			PageData pd1 = map.get(key);
			String countCategoryId = vo.getString("countCategoryId");
			String actualGrantAmount = vo.getString("actualGrantAmount");
			if (pd1 == null){
				PageData pd2 = new PageData();
				pd2.put(countCategoryId,actualGrantAmount);
				map.put(key,pd2);
			}else {
				pd1.put(countCategoryId,actualGrantAmount);
				map.put(key,pd1);
			}
		}
		return  map;
	}

	public List<PageData> mapAddPdlist(HashMap<String, PageData> map,List<PageData> list){
		for (String keyid : map.keySet()){
			PageData pd3 = new PageData();
			String[] split = keyid.split("\t");
			String id = split[0];
			String fillingUnitId = split[1];
			String fillingMonth = split[2];
			PageData pageData1 = map.get(keyid);
			for (Object pdid :pageData1.keySet()){
				pd3.put(pdid,pageData1.getString(pdid));
			}
			pd3.put("id",id);
			pd3.put("fillingUnitId",fillingUnitId);
			if(StringUtil.isNotBlank(fillingUnitId)) {
				PageData org = orgzationService.getCompanyNameById(fillingUnitId);
				if (org != null) {
					pd3.put("fillingUnitName",org.getString("name"));
				}
			}
			pd3.put("fillingMonth",fillingMonth);
			list.add(pd3);
		}
		return list;
	}

}
